﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TheOutfield.UmbExt.UniversalMediaPicker.Interfaces;
using TheOutfield.UmbExt.UniversalMediaPicker.Extensions;
using System.Net;
using ScribdNet = Scribd.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Web.UI.WebControls;

namespace TheOutfield.UmbExt.UniversalMediaPicker.Providers.Scribd
{
    public class ScribdProvider : AbstractProvider
    {
        private ScribdConfig config;
        private IConfigControl configControl;
        private ICreateControl createControl;

        public ScribdProvider()
        { }

        public ScribdProvider(string config)
            : base(config)
        {
            this.config = config.DeserializeJsonTo<ScribdConfig>();
        }

        public override string Alias
        {
            get { return "Scribd"; }
        }

        public override IConfigControl ConfigControl
        {
            get
            {
                if (configControl == null)
                    configControl = new ScribdConfigControl(this, Config);

                return configControl;
            }
        }

        public override ICreateControl CreateControl
        {
            get
            {
                if (createControl == null)
                    createControl = new ScribdCreateControl(this, Config);

                return createControl;
            }
        }

        public override IList<MediaItem> GetMediaItems(string parentId)
        {
            var mediaItems = new List<MediaItem>();

            EnsureScribdContext();

            // Force loading of Scribd docs
            var tmp = ScribdNet.Service.User.Documents;

            if (parentId == "-1")
            {
                // Create root folders
                mediaItems.Add(new MediaItem
                {
                    Id = "col:-1",
                    Title = "Collections",
                    Icon = UmbracoIcons.FolderOpen,
                    HasChildren = true,
                    PreviewImageUrl = "",
                    Selectable = false
                });

                mediaItems.Add(new MediaItem
                {
                    Id = "cat:-1",
                    Title = "Categories",
                    Icon = UmbracoIcons.FolderOpen,
                    HasChildren = true,
                    PreviewImageUrl = "",
                    Selectable = false
                });

                mediaItems.Add(new MediaItem
                {
                    Id = "all:-1",
                    Title = "All",
                    Icon = UmbracoIcons.FolderOpen,
                    HasChildren = true,
                    PreviewImageUrl = "",
                    Selectable = false
                });
            }
            else if (parentId.StartsWith("col:"))
            {
                var id = parentId.Substring(parentId.IndexOf(":") + 1);
                if (id == "-1")
                {
                    var cols = ScribdNet.Collection.GetCollections(ScribdNet.Collection.Scope.Both);
                    foreach (var col in cols)
                    {
                        var mi = col.ToMediaItem();
                        mi.Id = "col:"+ mi.Id;
                        mediaItems.Add(mi);
                    }
                }
                else
                {
                    var colId = Convert.ToInt32(id);
                    var docs = ScribdNet.Collection.GetCollectionDocuments(null, colId, true);
                    foreach (var doc in docs)
                    {
                        mediaItems.Add(doc.ToMediaItem());
                    }
                }
                    
            }
            else if (parentId.StartsWith("cat:"))
            {
                var id = parentId.Substring(parentId.IndexOf(":") + 1);
                if (id == "-1")
                {
                    // Root categories
                    var cats = ScribdNet.Category.GetCategories(false);
                    foreach (var cat in cats)
                    {
                        var mi = cat.ToMediaItem();
                        mi.Id = "cat:" + mi.Id;
                        mediaItems.Add(mi);
                    }
                }
                else
                {
                    var catId = Convert.ToInt32(id);

                    // Sub categories
                    var cats = ScribdNet.Category.GetCategories(catId);
                    foreach (var cat in cats)
                    {
                        var mi = cat.ToMediaItem();
                        mi.Id = "cat:" + mi.Id;
                        mediaItems.Add(mi);
                    }

                    // Documents
                    var docs = ScribdNet.Service.User.Documents;
                    foreach (var doc in docs)
                    {
                        if (doc.CategoryId == catId)
                            mediaItems.Add(doc.ToMediaItem());
                    }
                }
            }
            else if(parentId.StartsWith("all:"))
            {
                var id = parentId.Substring(parentId.IndexOf(":") + 1);
                if (id == "-1")
                {
                    for (var c = 'a'; c <= 'z'; c++)
                    {
                        mediaItems.Add(new MediaItem
                        {
                            Id = "all:" + c.ToString(),
                            Title = c.ToString().ToUpper(),
                            Icon = UmbracoIcons.FolderOpen,
                            PreviewImageUrl = "",
                            HasChildren = true,
                            Selectable = false
                        });
                    }

                    mediaItems.Add(new MediaItem
                    {
                        Id = "all:other",
                        Title = "Other",
                        Icon = UmbracoIcons.FolderOpen,
                        PreviewImageUrl = "",
                        HasChildren = true,
                        Selectable = false
                    });
                }
                else
                {
                    if (id != "other")
                    {
                        var docs = ScribdNet.Service.User.Documents;
                        foreach (var doc in docs)
                        {
                            if (doc.Title.ToLower().StartsWith(id.ToLower()))
                                mediaItems.Add(doc.ToMediaItem());
                        }
                    }
                    else
                    {
                        var docs = ScribdNet.Service.User.Documents;
                        foreach (var doc in docs)
                        {
                            if (Regex.IsMatch(doc.Title, "^[^A-Za-z]"))
                                mediaItems.Add(doc.ToMediaItem());
                        }
                    }
                }
            }

            return mediaItems;
        }

        public override MediaItem GetMediaItemById(string id)
        {
            // Connect to API, an retrive items
            if (EnsureScribdContext())
            {
                var docId = 0;
                if (int.TryParse(id, out docId))
                {
                    var doc = ScribdNet.Document.Download(docId);
                    return doc.ToMediaItem();
                }
            }

            return null;
        }

        public MediaItem CreateMediaItem(Stream fileStream,
            string title,
            string description,
            string tags,
            int collectionId,
            int categoryId)
        {
            EnsureScribdContext();

            // Upload file
            var doc = ScribdNet.Document.Upload(fileStream, ScribdNet.AccessTypes.Public, false);
            if (doc != null && doc.DocumentId > 0)
            {
                // Update info
                doc.Title = title;
                doc.Description = description;
                doc.TagList = new List<string>(tags.Split(','));

                if(categoryId > 0)
                    doc.CategoryId = categoryId;

                doc.Save();
                    
                if(collectionId > 0)
                    doc.AddToCollection(null, collectionId);

                // Update documents cache
                ScribdNet.Service.User.ReloadDocuments();

                // Return media item
                return doc.ToMediaItem();
            }

            return null;
        }

        public ListItem[] GetCollections()
        {
            var lis = new List<ListItem>();

            EnsureScribdContext();

            var cols = ScribdNet.Collection.GetCollections(ScribdNet.Collection.Scope.Both);
            foreach (var col in cols)
            {
                lis.Add(new ListItem(col.Name, col.ID.ToString()));
            }

            return lis.ToArray();
        }

        public ListItem[] GetCategories()
        {
            var lis = new List<ListItem>();

            EnsureScribdContext();

            var cats = ScribdNet.Category.GetCategories(true);
            foreach (var cat in cats)
            {
                lis.Add(new ListItem(cat.Name, cat.ID.ToString()));

                if (cat.SubCategories != null && cat.SubCategories.Count > 0)
                {
                    var buffer = HttpUtility.HtmlDecode("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                    foreach (var subCat in cat.SubCategories)
                    {
                        lis.Add(new ListItem(buffer + subCat.Name, subCat.ID.ToString()));
                    }
                }
            }

            return lis.ToArray();
        }

        public bool EnsureScribdContext()
        {
            if (ScribdNet.Service.APIKey != config.ApiKey &&
                ScribdNet.Service.SecretKey != config.SecretKey)
            {
                ScribdNet.Service.APIKey = config.ApiKey;
                ScribdNet.Service.SecretKey = config.SecretKey;
                ScribdNet.Service.EnforceSigning = true;
            }

            return true;
        }
    }
}